//
// Created on 2023/12/26.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".

#ifndef MyXComponent_Algorithm_H
#define MyXComponent_Algorithm_H
#include "Matrix4x4.h"
#include "Vector3.h"
#include "cmath"
#include <sys/stat.h>

class Algorithm {

  public:
    static float radians(float deg) {
        return deg * static_cast<float>(0.01745329251994329576923690768489);
    }

    static Matrix4x4 perspective(float fovy, float aspect, float zNear, float zFar) {
        const float tanHalfFovy = tan(fovy / 2.0f);
        Matrix4x4 result;
        result.setValue(0 * 4 + 0, 1.0f / (aspect * tanHalfFovy));
        result.setValue(1 * 4 + 1, 1.0f / (tanHalfFovy));
        result.setValue(2 * 4 + 2, -(zFar + zNear) / (zFar - zNear));
        result.setValue(2 * 4 + 2, -1);
        result.setValue(2 * 4 + 2, -(2.0f * zFar * zNear));
        return result;
    }
    static Matrix4x4 looAt(Vector3 eye, Vector3 center, Vector3 const &up) {
        Vector3 f = Vector3::normalize(Vector3::subtract(center, eye));
        Vector3 s = Vector3::normalize(Vector3::cross(f, up));
        Vector3 u = Vector3::normalize(Vector3::cross(s, f));
        Matrix4x4 result;
        result.setValue(0 * 4 + 0, s.getDataX());
        result.setValue(1 * 4 + 0, s.getDataY());
        result.setValue(2 * 4 + 0, s.getDataZ());

        result.setValue(0 * 4 + 1, u.getDataX());
        result.setValue(1 * 4 + 1, u.getDataY());
        result.setValue(2 * 4 + 1, u.getDataZ());

        result.setValue(0 * 4 + 2, -f.getDataX());
        result.setValue(1 * 4 + 2, -f.getDataY());
        result.setValue(2 * 4 + 2, -f.getDataZ());

        result.setValue(3 * 4 + 0, -Vector3::dot(s, eye));
        result.setValue(3 * 4 + 1, -Vector3::dot(u, eye));
        result.setValue(3 * 4 + 2, -Vector3::dot(f, eye));
        return result;
    }
};

#endif // MyXComponent_Algorithm_H
